package com.movitech.mobile.cz.base.sys;


import com.movitech.mobile.cz.base.common.aop.ServiceThrowable;
import com.movitech.mobile.cz.base.common.util.CommonConstants;
import com.movitech.mobile.cz.base.common.util.StringUtils;
import com.movitech.mobile.cz.base.util.UserUtils;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

//@Component
//@Aspect
public class DuplicateSubmitAop {

    private final static Logger logger = Logger.getLogger(DuplicateSubmitAop.class);
    /**
     * 环绕通知：
     *   环绕通知非常强大，可以决定目标方法是否执行，什么时候执行，执行时是否需要替换方法参数，执行完毕是否需要替换返回值。
     *   环绕通知第一个参数必须是org.aspectj.lang.ProceedingJoinPoint类型
//     */
//    @Around("execution(* com.movitech.mobile..*.*Controller.*(..))")
//    @Around("annotationGetMapping()")
    public Object doAroundAdvice(ProceedingJoinPoint proceedingJoinPoint){
        String errorTip = "正在处理中，请稍后。。。";
        String signatureName = proceedingJoinPoint.getSignature().getName();//方法名称
        System.out.println("====DuplicateSubmitAop==START==："+signatureName);
        boolean isRemove = false;
        String uuidToken = "";
        try {
            if(isHasGetRequestMethod(proceedingJoinPoint) || isContainPath(signatureName)){//过滤掉get请求
                System.out.println("====DuplicateSubmitAop==END==："+signatureName);
                return proceedingJoinPoint.proceed();
            }else {
                ////获取uuidToken的值
                RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();//获取RequestAttributes
                HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);//从获取RequestAttributes中获取HttpServletRequest的信息

                ///验证逻辑
//                uuidToken = request.getParameter("uuidToken");
                String userId = UserUtils.getCurrentUserId();
                if(StringUtils.isEmpty(userId)){
                    userId = UserUtils.getOuterCurrentUserId();
                }
                if(StringUtils.isNotEmpty(userId)){
                    uuidToken = userId;
                }
                System.out.println("====DuplicateSubmitAop==uuidToken=="+uuidToken);
                if (StringUtils.isNotEmpty(uuidToken)) {
                    String tokenItem = CommonConstants.MAP_DUPLICATE_FILTER_DATA.get(signatureName + "_" + uuidToken);
                    System.out.println("====DuplicateSubmitAop=1=tokenItem=="+tokenItem);
                    if (StringUtils.equalsIgnoreCase(tokenItem, CommonConstants.YES_INTEGER + "")) {
                        throw new RuntimeException(errorTip);
                    } else {
                        System.out.println("====DuplicateSubmitAop=2=tokenItem=="+tokenItem);
                        CommonConstants.MAP_DUPLICATE_FILTER_DATA.put(signatureName + "_" + uuidToken, CommonConstants.YES_INTEGER + "");
                    }
                }

                ///执行系统功能方法-调用执行目标方法
                isRemove = true;
                Object methodObj = proceedingJoinPoint.proceed();

                ////去除缓存中的值
                if (StringUtils.isNotEmpty(uuidToken)) {
                    CommonConstants.MAP_DUPLICATE_FILTER_DATA.remove(signatureName + "_" + uuidToken);
                }
                System.out.println("====DuplicateSubmitAop==END==："+signatureName);

                return methodObj;
            }
        } catch (Throwable e) {
            e.printStackTrace();
            logger.error(e);
            ////去除缓存中的值
            if(StringUtils.isNotEmpty(uuidToken)){
                if(isRemove){
                    CommonConstants.MAP_DUPLICATE_FILTER_DATA.remove(signatureName+"_"+uuidToken);
                }else{
                    throw new RuntimeException(errorTip,new ServiceThrowable());
                }
            }
            throw new RuntimeException(e.getMessage(),e.getCause());
        }
    }

    /**
     * 获取注解中对方法的日志类型 用于Controller层注解
     *
     * @param joinPoint
     *            切点
     * @return 方法描述
     * @throws Exception
     */
    public static boolean isHasGetRequestMethod(JoinPoint joinPoint) throws Exception {
        boolean hasGetRequest = false;
        String targetName = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] arguments = joinPoint.getArgs();
        Class targetClass = Class.forName(targetName);
        Method[] methods = targetClass.getMethods();
        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                Class[] clazzs = method.getParameterTypes();
                if (clazzs.length == arguments.length) {
                    GetMapping annotationGetMapping = method.getAnnotation(GetMapping.class);
                    if(annotationGetMapping != null){
                        hasGetRequest = true;
                        break;
                    }else{
                        RequestMapping annotationRequestMapping = method.getAnnotation(RequestMapping.class);
                        if(annotationRequestMapping != null){
                            RequestMethod[] arrRequestMethod = annotationRequestMapping.method();
                            if(arrRequestMethod!=null){
                                for (int i=0;i<arrRequestMethod.length;i++){
                                    if (arrRequestMethod[i] == RequestMethod.GET) {
                                        hasGetRequest = true;
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    break;
                }
            }
        }
        return hasGetRequest;
    }

    private boolean isContainPath(String path){
        boolean isContain = false;
        String[] arrPath = new String[]{"simple","searchList","initHome","getProjectListByRegionalCompanyId","getSuppliersList",
                "allList","getQualifiedSuppliersList","getSelectSupplierList","checkCodeOrNumber","isExistCompanyName","checkLoginName",
                "getSuppliersAll","getBlackSuppliersList","moreInfo","searchEvaluationList"};
        for (String item : arrPath) {
            if(StringUtils.equalsIgnoreCase(path,item)){
                isContain = true;
                break;
            }
        }
        return isContain;
    }
}
